package main

import (
	"bufio"
	"context"
	"flag"
	"fmt"
	"log"
	"net"
	"os"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"

	pb "a.local/generated_pb" // import ./util as u
)

var (
	port = flag.Int("port", 50051, "The server port")
)

type server struct {
	pb.UnimplementedGreeterServer
}


// --------------------------------------------------
// F0_ParseInitialInput processes initial input (SOW, CLI docs, notes) and returns processed text
func (s *server) F0_ParseInitialInput(ctx context.Context, req *pb.InitialInput) (*pb.TextSoW, error) {
	log.Printf("F0_ParseInitialInput called with SOW size: %d bytes, CLI size: %d bytes, notes: %s",
		len(req.SowDocx), len(req.CliDocx), req.Notes)

	return &pb.TextSoW{
		ProcessedSow:           "Mock processed SOW document content",
		ProcessedCli:           "Mock processed CLI change document content",
		ProcessedNotes:         "Mock processed notes: " + req.Notes,
		ClarificationQuestions: "Mock clarification: What is the expected network topology?",
		UsrAnswers:             "Mock user answers: Standard 3-tier architecture",
	}, nil
}

// F1_TextSoW2Testcases converts processed text to test cases
func (s *server) F1_TextSoW2Testcases(ctx context.Context, req *pb.TextSoW) (*pb.TestCases, error) {
	log.Printf("F1_TextSoW2Testcases called with processed SOW: %s", req.ProcessedSow[:min(50, len(req.ProcessedSow))])

	return &pb.TestCases{
		TestCases: []*pb.TestCase{
			{
				Name: "Mock Test Case 1: Network Connectivity",
				Steps: []*pb.TestCase_StepPair{
					{Step:   "Ping from host A to host B", Expect: "Ping successful with < 1ms latency",},
					{Step:   "Check routing table", Expect: "Default route points to gateway",},
				},
			},
			{
				Name: "Mock Test Case 2: Service Availability",
				Steps: []*pb.TestCase_StepPair{
					{Step:   "Check HTTP service on port 80", Expect: "HTTP 200 response received",},
				},
			},
		},
	}, nil
}

// F2_GetCommonNetworkSetup generates network setup configuration
func (s *server) F2_GetCommonNetworkSetup(ctx context.Context, req *pb.TextSoW) (*pb.NetworkSetup, error) {
	log.Printf("F2_GetCommonNetworkSetup called with processed SOW")

	return &pb.NetworkSetup{
		Id:         "mock-network-setup-1",
		Topox:      `mock topox`,
		ConftestPy: `mock conftest.py`,
	}, nil
}

// F3_GenerateScript generates a Python test script
func (s *server) F3_GenerateScript(ctx context.Context, req *pb.X) (*pb.TestScript, error) {
	log.Printf("F3_GenerateScript called for test case: %s", req.TestCase.Name)
	return &pb.TestScript{
		Pyscript: "mocked script",
	}, nil
}

// F4_RunAndGetLog runs a test script and returns the result
func (s *server) F4_RunAndGetLog(ctx context.Context, req *pb.TestUnit) (*pb.TestResult, error) {
	log.Printf("F4_RunAndGetLog called with network setup: %s", req.NetworkSetup.Id)
	// Mock test execution
	return &pb.TestResult{
		Status: "passed",
		Log:    `Mocked log`,
		Script: req.Script, // Return original script since test passed
	}, nil
}

func stop(s *grpc.Server) {
	s.GracefulStop()
	log.Println("\t 🚮️ Server gracefully shut down.")
}

func main() {
	fmt.Println("Hi from main")
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	reflection.Register(s)
	log.Printf("server listening at %v", lis.Addr())

	// --------------------------------------------------
	// Start the server in a goroutine
	go func() {
		if err := s.Serve(lis); err != nil {
			log.Fatalf("failed to serve: %v", err)
		}
	}()
	defer stop(s) // 🐢 if any thing bad (kinda finally)

	// wait for an input
	fmt.Println("Press 'Enter' to exit...")
	scn := bufio.NewScanner(os.Stdin)
	scn.Scan()
	log.Println("👋 bye.")
}
